package com.zdp.oauth.controller;

import cn.hutool.core.util.StrUtil;
import com.zdp.oauth.common.JsonUtils;
import com.zdp.oauth.entity.LoginUserInfo;
import com.zdp.oauth.entity.ResultInfo;
import com.zdp.oauth.filter.AccessContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * <h1>用户信息控制层</h1>
 */
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @Autowired
    private RestTemplate restTemplate;

    @Resource
    private HttpServletRequest httpServletRequest;

    private static final String authenticationServerId = "AUTHENTICATION-CENTER-JWT";

    /**
     * <h2>通过授权中心暴露的/check/token端点解析token并获取用户信息(从token增强的属性中获取)</h2>
     * @apiNote
     * 获取用户信息，这个需要配置资源服务可以访问不然会被403
     */
    @GetMapping("/user-info-by/authentication-center/check/token")
    public ResultInfo<LoginUserInfo> getCurrentUser() {
        // 这个只能获取到登录的账号信息
        // Object principal = authentication.getPrincipal();
        String authorization = httpServletRequest.getHeader("Authorization");
        if (StringUtils.isBlank(authorization)) throw new RuntimeException("authorization token is empty");
        authorization = StrUtil.removePrefix(authorization, "Bearer ");

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("token", authorization);

        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);

        // 根据授权服务的id从注册中心随机获取实例
        ServiceInstance serviceInstance = loadBalancerClient.choose(authenticationServerId);
        if (Objects.isNull(serviceInstance)) throw new RuntimeException(authenticationServerId + " server is down");
        // 打印实例源数据
        log.info("Nacos Client Info: [{}], [{}], [{}]",
                serviceInstance.getServiceId(), serviceInstance.getInstanceId(),
                JsonUtils.objectToJson(serviceInstance.getMetadata()));
        // 请求url
        String authorizationCenterCheckTokenUrl = "http://%s:%s/authentication-center/oauth/check_token";
        // 拼接ip:port
        String requestUrl = String.format(authorizationCenterCheckTokenUrl, serviceInstance.getHost(), serviceInstance.getPort());
        log.info("authorization center check token url: [{}]", requestUrl);
        // 请求授权服务的/check/token端点
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(requestUrl, request, String.class);
        String body = responseEntity.getBody();

        return new ResultInfo<LoginUserInfo>(200, "", httpServletRequest.getServletPath(), JsonUtils.jsonToPojo(body, LoginUserInfo.class));
    }

    /**
     * <h2>解析jwt token获取用户信息</h2>
     */
    @GetMapping("/user-info-by/parse/jwt/token")
    public ResultInfo<LoginUserInfo> getCurrentUserInfo() {
        return new ResultInfo<LoginUserInfo>(200, "", httpServletRequest.getServletPath(), AccessContext.getLoginUserInfo());
    }
}
